import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;

public class LR extends JFrame implements ActionListener {
    private static String Str = null; // 输入串
    private static String Sub = null; //输入串的待处理部分
    private static boolean acc = false;// 是否已处理完输入串
    private static boolean bResult = false;// 是否出错

    // Goto表，即每个状态遇见非终结符时的动作
    private static int[][] Goto = new int[][]{{1, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {8, 2, 3},
            {0, 0, 0}, {0, 9, 3}, {0, 0, 10}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};


    private static Stack<String> stack = new Stack<String>();// 状态栈，栈中元素都是String类型
    private static String input;

    /**
     * @param state 状态
     * @param fzjf 遇见的非终结符
     * fzjf == 'E'代表是Goto表的第一列
     * fzjf == 'T'代表是Goto表的第二列
     * fzjf == 'F'代表是Goto表的第三列
     */
    private static JTextArea res = new JTextArea(18, 50);
    private static JTextField tf;
    private JButton jb1;
    private JButton jb2;
    private JLabel jl1;
    private JLabel jl2;

    public LR() {
        super("LR分析器");
        this.setSize(600, 500);
        this.setLocation(200, 150);
        this.setLayout(null);
        tf = new JTextField(30);
        jb1 = new JButton("清空文本区");
        jb2 = new JButton("优先分析");
        jl1 = new JLabel("输入字符串：");
        jl2 = new JLabel("分析结果：");
        jl1.setFont(new Font("楷书", Font.BOLD, 14));
        jl2.setFont(new Font("楷书", Font.BOLD, 14));
        jl1.setSize(100, 25);
        jl1.setLocation(10, 10);
        this.add(jl1);
        tf.setSize(400, 25);
        tf.setLocation(120, 10);
        this.add(tf);
        jl2.setSize(90, 25);
        jl2.setLocation(10, 40);
        this.add(jl2);
        res.setEditable(false);
        JScrollPane sc = new JScrollPane(res, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        sc.setSize(580, 350);
        sc.setLocation(10, 70);
        this.add(sc);
        jb1.setBounds(100, 430, 100, 25);
        jb2.setBounds(400, 430, 100, 25);
        this.add(jb1);
        this.add(jb2);
//        jb1.addActionListener(this);
        jb1.addActionListener(new ActionListener() {

            // 当按钮被点击时，就会触发 ActionEvent事件
            // actionPerformed 方法就会被执行
            public void actionPerformed(ActionEvent e) {
                res.setText("");
            }
        });



        jb2.addActionListener(this);
        this.setVisible(true);
    }

    public static void Gto(int state, char fzjf) {
        int i = -1;
        if (fzjf == 'E')
            i = 0;
        if (fzjf == 'T')
            i = 1;
        if (fzjf == 'F')
            i = 2;

        stack.push(fzjf + ""); //将非终结符压入栈中，字符+空串转化为字符串
        stack.push(Goto[state][i] + "");//将Goto表中对应的状态压入栈中

    }

    /**
     * e1代表缺少运算对象 将“id”压入栈中，随即将相应的状态压入栈中
     */
    public static void e1() {
        res.append("缺少运算对象\n");
        System.out.println("缺少运算对象");
        stack.push("id");
        stack.push(String.valueOf(3));
//		bResult = true;
//若该行不注释掉，程序遇到输入错误就会立即停止	；若注释掉，程序不会立即停止，而是会恢复错误
    }

    public static void e3() {
        res.append("缺少算符\n");
        System.out.println("缺少算符");
        stack.push("+");
        stack.push("" + 6);
//		bResult = true;
    }

    public static void e3_() {
        res.append("缺少算符\n");
        System.out.println("缺少算符");
        stack.push("*");
        stack.push("" + 7);
		bResult = true;
    }

    public static void e2() {
        res.append("不匹配的右括号\n");
        System.out.println("不匹配的右括号");
        Sub = Sub.substring(1, Sub.length());
//		bResult = true;
    }

    public static void e4() {
        res.append("缺少右括号\n");
        System.out.println("缺少右括号");
        stack.push("");
        stack.push(11 + "");
//		bResult = true;
    }

    public static void e5() {
        res.append("算符错误\n");
        System.out.println("算符错误");
        stack.push("+");
        stack.push(6 + "");
        Sub = Sub.substring(1, Sub.length());
		bResult = true;
    }

    public void LR(String input) {
        // TODO Auto-generated method stub
//        new test();
//        input=tf.getText();
//        System.out.println(input);

        Sub = input + "#";   //初始时Sub = Str

        int y;
        boolean flag = false;

        // 0状态先进栈
        stack.push(String.valueOf(0));
        while (!bResult && acc == false) {
            switch (stack.peek().charAt(0)) {
                case '0':
                    if (Sub.substring(0, 2).equals("id")) {
                        stack.push("id");
                        stack.push("" + 5);
                        Sub = Sub.substring(2, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("(")) {
                        stack.push("(");
                        stack.push("" + 4);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else {
                        e1();
                    }
                    break;
                case '1':
                    if ("1".equals(stack.peek())) {
                        if (Sub.substring(0, 1).equals("+")) {
                            stack.push("id");
                            stack.push("" + 6);
                            Sub = Sub.substring(1, Sub.length());
                            res.append("移进\n");
                            System.out.println("移进");
                        } else if (Sub.substring(0, 1).equals("#")) {
                            acc = true;
                            res.append("接受\n");
                            System.out.println("接受");
                        } else {
                            e3();
                        }
                        break;
                    } else if (stack.peek().charAt(1) == '0') {
                        if (Sub.substring(0, 1).equals("+")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                            res.append("按T->T*F归约\n");
                            System.out.println("按T->T*F归约");
                        } else if (Sub.substring(0, 1).equals(")")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                            res.append("按T->T*F归约\n");
                            System.out.println("按T->T*F归约");
                        } else if (Sub.substring(0, 1).equals("#")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                            res.append("按T->T*F归约\n");
                            System.out.println("按T->T*F归约");
                        } else if (Sub.substring(0, 1).equals("*")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                            res.append("按T->T*F归约\n");
                            System.out.println("按T->T*F归约");
                        } else {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                            res.append("按T->T*F归约\n");
                            System.out.println("按T->T*F归约");
                        }
                        break;
                    } else {
                        if (Sub.substring(0, 1).equals("+")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                            res.append("按F->(E)归约\n");
                            System.out.println("按F->(E)归约");
                        } else if (Sub.substring(0, 1).equals(")")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                            res.append("按F->(E)归约\n");
                            System.out.println("按F->(E)归约");
                        } else if (Sub.substring(0, 1).equals("#")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                            res.append("按F->(E)归约\n");
                            System.out.println("按F->(E)归约");
                        } else if (Sub.substring(0, 1).equals("*")) {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                            res.append("按F->(E)归约\n");
                            System.out.println("按F->(E)归约");
                        } else {
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            stack.pop();
                            Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                            res.append("按F->(E)归约\n");
                            System.out.println("按F->(E)归约");
                        }
                        break;
                    }
                case '2':
                    if (Sub.substring(0, 1).equals("*")) {
                        stack.push("*");
                        stack.push("" + 7);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("+")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->T归约\n");
                        System.out.println("按E->T归约");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->T归约\n");
                        System.out.println("按E->T归约");
                    } else if (Sub.substring(0, 1).equals("#")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->T归约\n");
                        System.out.println("按E->T归约");
                    } else {
                        e3_();
                    }
                    break;
                case '3':
                    if (Sub.substring(0, 1).equals("+")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                        res.append("按T->F归约\n");
                        System.out.println("按T->F归约");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                        res.append("按T->F归约\n");
                        System.out.println("按T->F归约");
                    } else if (Sub.substring(0, 1).equals("#")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                        res.append("按T->F归约\n");
                        System.out.println("按T->F归约");
                    } else if (Sub.substring(0, 1).equals("*")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                        res.append("按T->F归约\n");
                        System.out.println("按T->F归约");
                    } else {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'T');
                        res.append("按T->F归约\n");
                        System.out.println("按T->F归约");
                    }
                    break;
                case '4':
                    if (Sub.substring(0, 2).equals("id")) {
                        stack.push("id");
                        stack.push("" + 5);
                        Sub = Sub.substring(2, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("(")) {
                        stack.push("(");
                        stack.push("" + 4);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        e2();
                    } else
                        e1();
                    break;
                case '5':
                    if (Sub.substring(0, 1).equals("+")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                        res.append("按F->id归约\n");
                        System.out.println("按F->id归约");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                        res.append("按F->id归约\n");
                        System.out.println("按F->id归约");
                    } else if (Sub.substring(0, 1).equals("#")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                        res.append("按F->id归约\n");
                        System.out.println("按F->id归约");
                    } else if (Sub.substring(0, 1).equals("*")) {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                        res.append("按F->id归约\n");
                        System.out.println("按F->id归约");
                    } else {
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'F');
                        res.append("按F->id归约\n");
                        System.out.println("按F->id归约");
                    }
                    break;
                case '6':
                    if (Sub.length() > 1) {
                        if (Sub.substring(0, 1).equals("(")) {
                            stack.push("(");
                            stack.push("" + 4);
                            Sub = Sub.substring(1, Sub.length());
                            res.append("移进\n");
                            System.out.println("移进");
                        } else if (Sub.substring(0, 2).equals("id")) {
                            stack.push("id");
                            stack.push("" + 5);
                            Sub = Sub.substring(2, Sub.length());
                            res.append("移进\n");
                            System.out.println("移进");
                        } else if (Sub.substring(0, 1).equals(")")) {
                            e2();
                        }
                    } else
                        e1();
                    break;
                case '7':
                    if (Sub.substring(0, 2).equals("id")) {
                        stack.push("id");
                        stack.push("" + 5);
                        Sub = Sub.substring(2, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("(")) {
                        stack.push("(");
                        stack.push("" + 4);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("(")) {
                        stack.push("(");
                        stack.push("" + 4);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        e2();
                    } else
                        e1();
                    break;
                case '8':
                    if (Sub.substring(0, 1).equals("+")) {
                        stack.push("+");
                        stack.push("" + 6);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        stack.push(")");
                        stack.push("" + 11);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("#")) {
                        e4();
                    } else if (Sub.substring(0, 1).equals("*")) {
                        e5();
                    } else
                        e3();
                    break;
                case '9':
                    if (Sub.substring(0, 1).equals("*")) {
                        stack.push("*");
                        stack.push("" + 7);
                        Sub = Sub.substring(1, Sub.length());
                        res.append("移进\n");
                        System.out.println("移进");
                    } else if (Sub.substring(0, 1).equals("+")) {
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->E+T归约\n");
                        System.out.println("按E->E+T归约");
                    } else if (Sub.substring(0, 1).equals(")")) {
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->E+T归约\n");
                        System.out.println("按E->E+T归约");
                    } else if (Sub.substring(0, 1).equals("#")) {
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->E+T归约\n");
                        System.out.println("按E->E+T归约");
                    } else {
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        stack.pop();
                        Gto((int) stack.peek().charAt(0) - (int) '0', 'E');
                        res.append("按E->E+T归约\n");
                        System.out.println("按E->E+T归约");
                    }
                    break;

            }

        }
        if (acc) {
            res.append("匹配成功\n");
            System.out.println("匹配成功");
        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        input = tf.getText();
        System.out.println(input);
        LR(input);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    System.out.println(info.getClassName());
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        new LR();
    }
}